#include "Bone.h"
#include "math.h"
#include "Skeleton.h"

Bone::Bone(tstring Name, float length,int id)
	:SkeletonNode(Name),m_ID(id),
	m_Start(DAEFloat3(0,0,0)),
	m_End(DAEFloat3(length,0,0)),
	m_pIndexBuffer(NULL),
	m_pVertexBuffer(NULL),
	m_HasGeometry(false)
{
	m_GlobalTrans.SetAsIdentity();
}

Bone::~Bone(void)
{
	delete m_pVertexBuffer;
	delete m_pIndexBuffer;
}

void Bone::SetTransform(float tx, float ty,float tz, float rx, float ry, float rz, float sx, float sy,float sz)
{
	m_InitialPose.SetTranslation(tx,ty,tz);
	m_InitialPose.SetRotation(rx,ry,rz);
	//m_InitialPose.SetScale(sx,sy,sz);
	
	DAEMatrix transform = m_InitialPose.GetCompiledMatrix();
	transform.Inverse(m_BoneInv);
}


void Bone::CreateBoneGeometry(){
	// 7 vertices needed
	VertexList* vl = new VertexList(7);

	vl->AddSemantic(POSITION,3);
	vl->AddSemantic(TEXCOORD,2);

	int positionOffset = vl->GetOffset(POSITION);
	

	DAEFloat3 axis;
	m_End.Subtract(axis,m_Start);
	float width = sqrt(axis.SquaredLength()) / 5.0f;
	axis.Scale(axis,.4f);
	// place ridge at 30%
	// normal bone axis is X axis , place 4 extra points
	// at y & z positions.
	
	DAEFloat3 p2(m_Start.x +axis.x, m_Start.y + width/2.0f,m_Start.z + width/2.0f);
	DAEFloat3 p3(m_Start.x +axis.x, m_Start.y - width/2.0f,m_Start.z + width/2.0f);
	DAEFloat3 p4(m_Start.x +axis.x, m_Start.y - width/2.0f,m_Start.z - width/2.0f);
	DAEFloat3 p5(m_Start.x +axis.x, m_Start.y + width/2.0f,m_Start.z - width/2.0f);
	
	m_InitialPose.TransformVector(m_Start,m_Start);
	m_InitialPose.TransformVector(m_End,m_End);
	m_InitialPose.TransformVector(p2,p2);
	m_InitialPose.TransformVector(p3,p3);
	m_InitialPose.TransformVector(p4,p4);
	m_InitialPose.TransformVector(p5,p5);

	
	vl->AddVertexData(0,positionOffset,&m_Start);
	vl->AddVertexData(1,positionOffset,&m_End);
	vl->AddVertexData(2,positionOffset,&p2);
	vl->AddVertexData(3,positionOffset,&p3);
	vl->AddVertexData(4,positionOffset,&p4);
	vl->AddVertexData(5,positionOffset,&p5);
	vl->AddVertexData(6,positionOffset,&p2);

	vl->AddVertexData(7,positionOffset,&m_End);
	vl->AddVertexData(8,positionOffset,&m_End);
	vl->AddVertexData(9,positionOffset,&m_End);

	int tcOffset = vl->GetOffset(TEXCOORD);

	DAEFloat2 tc0(0.5f,0.0f);
	DAEFloat2 tc1(0.125f,1.0f);
	vl->AddVertexData(0,tcOffset,&tc0);
	vl->AddVertexData(1,tcOffset,&tc1);
	DAEFloat2 tc2(0.0f,0.5f);
	DAEFloat2 tc3(0.25f,0.5f);
	DAEFloat2 tc4(0.5f,0.5f);
	DAEFloat2 tc5(0.75f,0.5f);
	DAEFloat2 tc6(1.0f,0.5f);
	DAEFloat2 tc7(0.375f,1.0f);
	DAEFloat2 tc8(0.625f,1.0f);
	DAEFloat2 tc9(0.875f,1.0f);
	vl->AddVertexData(2,tcOffset,&tc2);
	vl->AddVertexData(3,tcOffset,&tc3);
	vl->AddVertexData(4,tcOffset,&tc4);
	vl->AddVertexData(5,tcOffset,&tc5);
	vl->AddVertexData(6,tcOffset,&tc6);
	vl->AddVertexData(7,tcOffset,&tc7);
	vl->AddVertexData(8,tcOffset,&tc8);
	vl->AddVertexData(9,tcOffset,&tc9);

	TriangleList* tl = new TriangleList(8);
	tl->AddIndexedFace(0,5,4);
	tl->AddIndexedFace(0,4,3);
	tl->AddIndexedFace(0,3,2);
	tl->AddIndexedFace(0,5,6);

	tl->AddIndexedFace(8,4,5);
	tl->AddIndexedFace(7,3,4);
	tl->AddIndexedFace(1,2,3);
	tl->AddIndexedFace(9,6,5);
	
	//m_pVertexBuffer = device->Compile(vl);
	//m_pIndexBuffer = device->Compile(tl);
	// no need to keep these around
	delete vl;
	delete tl;

	//SkeletonNode::CreateBoneGeometry(device);
}

/*
void Bone::Draw(Level* level,ShaderMaterial * material)const
{
	if ( m_pVertexBuffer == NULL || m_pIndexBuffer == NULL )
		return;
	// calculate chain of matrices.
	//m_GlobalMatrix = m_World->GetCompiledMatrix();
	//Bone* parent = this->GetParent();
	//while (parent != NULL){
	//	DAEMatrix pm = parent->m_World->GetCompiledMatrix();
	//	//m_GlobalMatrix.Multiply(&m_GlobalMatrix,&pm);
	//	pm.Multiply(&m_GlobalMatrix,&m_GlobalMatrix);
	//	parent = parent->GetParent();
	//}

	FXParameter* world = (FXParameter*) material->CustomizeParameterByName(_T("gWorld"));
	world->SetValue(&m_GlobalTrans);
	material->SetInEffect(level->GetDevice(),world);
	
	material->CommitChanges();
	
	m_pVertexBuffer->Draw(device);
	m_pIndexBuffer->Draw(device);

	vector<SkeletonNode*>::const_iterator it;
	for (it=m_ChildNodes.begin(); it!= m_ChildNodes.end(); ++it)
	{
		SkeletonNode* child = *it;
		child->Draw(level,material);
	}
}
*/
/*
void Bone::Animate(Skeleton* skeleton,float time)
{
	if ( m_pAnimation != NULL ){
		DAEFloat4 quat;
		DAEFloat3 pivot;
		DAEFloat3 scale;
		m_pAnimation->GetTransformAt(time,quat,pivot,scale);
		//m_pAnimation->GetTransformAt(10,quat,pivot,scale);
		//DAEFloat3 pivot = GetPivot();
		SkeletonNode* parent = this->GetParent();
		
		if ( parent == NULL )
		{
		TRSTransform trs;
		trs.SetRotation(quat.x,quat.y,quat.z);
		trs.SetTranslation(pivot.x,pivot.y,pivot.z);
		//trs.SetScale(scale.x,scale.y,scale.z);
		//m_AnimTransform.SetTransformation(pivot,quat);
		//DAEMatrix anim = m_AnimTransform.GetCompiledMatrix();
		DAEMatrix anim = trs.GetCompiledMatrix();
		m_BoneInv.Multiply(&m_GlobalTrans,&anim);
		//}else{
		//	// rotate the pivot point with the parent transformation.
		//	DAEFloat3 newPivot;
		//	DAEMatrix pmatrix = parent->GetGlobalTransformation();
		//	pmatrix.TransformVector(newPivot,pivot);
		//	m_AnimTransform.SetTransformation(newPivot,quat);
		//	m_BoneInv.Multiply(&m_GlobalTrans,&m_AnimTransform.GetCompiledMatrix());

		//}
		
	}else{
		m_GlobalTrans.SetAsIdentity();
	}
	skeleton->SetBoneMatrix(m_ID,m_GlobalTrans);
	vector<SkeletonNode*>::const_iterator it;
	for (it = m_ChildNodes.begin();it!=m_ChildNodes.end();++it)
	{
		SkeletonNode* child =*it;
		child->Animate(skeleton,time);
	}
}
*/